package 顺序打印ABC;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Copyright (C) 2023 思创数码科技股份有限公司
 * <p/>
 * 版权所有
 * <p/>
 * 类名　　  : ReetrantLockAndCondtionImpl
 * 功能概要  :
 *
 * @Author : yangwk
 * @Date : 2024/4/2 23:30
 */
public class ReentrantLockAndConditionImpl {
    public static void main(String[] args) throws InterruptedException {
        ReentrantLockAndConditionImpl reentrantLockAndCondition = new ReentrantLockAndConditionImpl();
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        executorService.submit(reentrantLockAndCondition.new ThreadA());
        executorService.submit(reentrantLockAndCondition.new ThreadB());
        executorService.submit(reentrantLockAndCondition.new ThreadC());
        Thread.currentThread().join(1000000);
    }

    String threadNameA = "A";
    String threadNameB = "B";
    String threadNameC = "C";
    Condition condition1;
    Condition condition2;
    Condition condition3;
    ReentrantLock reentrantLock;
    ReentrantLockAndConditionImpl() {
        reentrantLock = new ReentrantLock();
        condition1 = reentrantLock.newCondition();
        condition2 = reentrantLock.newCondition();
        condition3 = reentrantLock.newCondition();
    }

    final AtomicInteger atomicInteger1 = new AtomicInteger(1);

    class ThreadA implements Runnable {
        @Override
        public void run() {
            while (true) {
                reentrantLock.lock();
                while (atomicInteger1.get() % 3 != 1) {
                    try {
                        condition1.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(threadNameA);
                atomicInteger1.incrementAndGet();
                System.out.println(atomicInteger1);
                condition2.signal();
                reentrantLock.unlock();
            }

        }
    }

    class ThreadB implements Runnable {

        @Override
        public void run() {
            while (true) {
                reentrantLock.lock();
                while (atomicInteger1.get() % 3 != 2) {
                    try {
                        condition2.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(threadNameB);
                atomicInteger1.incrementAndGet();
                System.out.println(atomicInteger1);
                condition3.signal();
                reentrantLock.unlock();
            }
        }
    }

    class ThreadC implements Runnable {

        @Override
        public void run() {
            while (true) {
                reentrantLock.lock();
                while (atomicInteger1.get() % 3 != 0) {
                    try {
                        condition3.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(threadNameC);
                atomicInteger1.incrementAndGet();
                System.out.println(atomicInteger1);
                condition1.signal();
                reentrantLock.unlock();
            }
        }
    }
}
